#include <iostream>
#include "ConsoleApp.hpp"

namespace wolf
{
    using namespace std;
    //
    void ConsoleApp::putChar( int c )
    {
        SDL_mutexP( console->consoleLock ); // Lock
        console->write( c );
        SDL_mutexV( console->consoleLock ); // Unlock
    }

    int ConsoleApp::readChar( void )
    {
        int c;
        do
        {
            SDL_mutexP( console->consoleLock ); // Lock
            c = console->getInput();
            if( c != -1 )
                console->setInput( 0 );
            else
            {
                console->setInput( -1 );
            }
            if( c == '\b' ) cout << "hihi" << endl;
            SDL_mutexV( console->consoleLock ); // Unlock
            SDL_Delay( 1 );
        }
        while ( !c && c != -1 ); // -1 is a flag to console ended.
        return c;
    }

    bool ConsoleApp::hasChar( void )
    {
        SDL_mutexP( console->consoleLock ); // Lock
        bool ret = console->getInput();
        SDL_mutexV( console->consoleLock ); // Unlock
        return ret;
    }

    void ConsoleApp::clear( void )
    {
        SDL_mutexP( console->consoleLock ); // Lock
        console->clear();
        SDL_mutexV( console->consoleLock ); // Unlock
    }

    void ConsoleApp::setColor( const Color &color )
    {
        SDL_mutexP( console->consoleLock ); // Lock
        console->setColor( color );
        SDL_mutexV( console->consoleLock ); // Unlock
    }


    const Color ConsoleApp::getColor( void )
    {
        SDL_mutexP( console->consoleLock ); // Lock
        Color ret = console->getColor();
        SDL_mutexV( console->consoleLock ); // Unlock
        return ret;
    }

    void ConsoleApp::getXY( int &x, int &y )
    {
        SDL_mutexP( console->consoleLock ); // Lock
        x = console->getCursorColumn();
        y = console->getCursorLine();
        SDL_mutexV( console->consoleLock ); // Unlock
    }

    void ConsoleApp::gotoXY( int x, int y )
    {
        SDL_mutexP( console->consoleLock ); // Lock
        console->setCursorColumn( x );
        console->setCursorLine( y );
        SDL_mutexV( console->consoleLock ); // Unlock
    }

    string ConsoleApp::getLine( void )
    {
        string result;
        int c = readChar();
        while( c != '\n' && c != -1 )
        {
            if( c != '\b' )
            {
                result += c;
                putChar( c );
            }
            else
            {
                int sz = result.size();
                if( sz > 0 )
                {
                    result.resize( result.size() - 1 );
                    int x, y;
                    getXY( x, y );
                    if( x > 0 ) --x;
                    else if( y > 0 )
                    {
                        --y;
                        x = console->getColumnsCount() - 1;
                    }
                    gotoXY( x, y );
                }
            }
            c = readChar();
        }
        if(c=='\n') putChar('\n');
        return result;
    }

    void ConsoleApp::sendMessage(ConsoleMessage *message)
    {
        SDL_mutexP( console->consoleLock ); // Lock
        console->mainQueue.push(message);
        SDL_mutexV( console->consoleLock ); // Unlock
    }

    ConsoleMessage *ConsoleApp::receiveMessage( void)
    {
        ConsoleMessage *message = NULL;
        SDL_mutexP( console->consoleLock ); //Lock
        if(!console->mainQueue.empty())
        {
            message = console->mainQueue.front();
            console->mainQueue.pop();
        }
        SDL_mutexV( console->consoleLock ); //unlock
        return message;
    }
}
